'use strict';
const {
  Model
} = require('sequelize');
const bcrypt = require('bcrypt');
module.exports = (sequelize, DataTypes) => {
  class User extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      // 关联模型
      models.User.hasMany(models.Course, { as: 'courses' });
      models.User.belongsToMany(models.Course, {
        as: 'likeCourses',
        through: models.Like,
        foreignKey: 'userId'
      });
    }
  }
  User.init({
    email: {
      type: DataTypes.STRING,
      allowNull: false,
      unique: true,
      validate: {
        notNull: {  msg: '邮箱不能为空' },
        notEmpty: { msg: '邮箱不能为空' },
        isEmail: { msg: '邮箱格式不正确' },
        async isUnique(value) {
          const user = await User.findOne({ where: { email: value } });
          if (user) {
            return new Error('邮箱已存在, 请直接登录');
          }
        }
      },
    },
    username: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        notNull: { msg: '用户名必须填写' },
        notEmpty: { msg: '用户名不能为空' },
        len: {
          args: [2, 20],
          msg: '用户名长度必须在 2 到 20 个字符之间'
        },
        async isUnique(value) {
          const user = await User.findOne({ where: { username: value } });
          if (user) {
            return new Error('用户名已存在, 请直接登录');
          }
        }
      },
    },
    password: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        notNull: { msg: '密码必须填写' },
        notEmpty: { msg: '密码不能为空' },
        // len: {
        //   args: [6, 20],
        //   msg: '密码长度必须在 6 到 20 个字符之间'
        // }
      },
      // 不在路由代码中校验密码，处理麻烦点，而是在 model 模型中 set 函数校验密码
      set(value) {
        if (value.length >= 6 && value.length <= 20) {
          const salt = bcrypt.genSaltSync(10);
          const hash = bcrypt.hashSync(value, salt);
          this.setDataValue('password', hash);
        } else {
          throw new Error('密码长度必须在 6 到 20 个字符之间');
        }
      }
    },
    nickname: {
      type: DataTypes.STRING,
      allowNull: false,
      validate: {
        notNull: { msg: '昵称必须填写' },
        notEmpty: { msg: '昵称不能为空' },
        len: {
          args: [2, 20],
          msg: '昵称长度必须在 2 到 20 个字符之间'
        }
      }
    },
    sex: {
      type: DataTypes.TINYINT,
      allowNull: false,
      validate: {
        notNull: { msg: '性别必须填写' },
        notEmpty: { msg: '性别不能为空' },
        isIn: {
          args: [[0, 1, 2]],
          msg: '性别只能是 0(男), 1(女), 2(未选择)'
        }
      }
    },
    company: DataTypes.STRING,
    introduce: DataTypes.TEXT,
    role: {
      type: DataTypes.TINYINT,
      allowNull: false,
      validate: {
        notNull: { msg: '角色必须选择' },
        notEmpty: { msg: '角色不能为空' },
        isIn: {
          args: [[0, 100]],
          msg: '角色只能是 0(普通用户), 100(管理员)'
        }
      }
    },
    avatar: {
      type: DataTypes.STRING,
      validate: {
        isUrl: { msg: '头像地址不正确' }
      }
    },
  }, {
    sequelize,
    modelName: 'User',
  });
  return User;
};